#include "lib/svg.cpp"
#include "lib/web.cpp"
#include "ctime"
#include "cstdlib"

string _2str(int d) {
	stringstream ss;
	ss << d;
	return ss.str();
}

int _2int(const string & s) {
	stringstream ss(s);
	int d;
	ss >> d;
	return d;
}

string _vec2str(const vector<int> & vec) {
	stringstream ss;
	I(i, vec.size())
		ss << vec[i] << " ";
	return ss.str();
}

vector<int> _str2vec(const string & s) {
	vector<int> vec;
	stringstream ss(s);
	while (ss) {
		int v;
		ss >> v;
		if (ss) vec.push_back(v);
	}
	return vec;
}

int rand_int(int min, int max) {
	int r = rand();
	return min+r%(max-min);
}

bool in_snake(const vector<int> & snake, int x, int y) {
	I(i, snake.size()/2) {
		int x1 = snake[2*i];
		int y1 = snake[2*i+1];
		if (x1==x and y1==y) return true;
	}
	return false;
}

void rand_dot(const vector<int> & snake, int width, int height) {
	while (true) {
		int x = rand_int(0, width-1);
		int y = rand_int(0, height-1);
		if (in_snake(snake, x, y)) continue;
		data["dot_x"] = _2str(x);
		data["dot_y"] = _2str(y);
		break;
	}
}

int main() {
	srand(time(0));
	string bg_color = "#CCFFCC";
	string line_color = "#333333";
	string dot_color = "#CC0000";
	int width = 15;
	int height = 15;
	int line_width = 20;

	if (not data.has("snake")) {
		data["snake"] = "0 0";
		data["head_x"] = "1";
		data["head_y"] = "0";
	}
	vector<int> snake_data = _str2vec(data["snake"]);
	if (not data.has("dot_x"))
		rand_dot(snake_data, width, height);
	int head_x = _2int(data["head_x"]);
	int head_y = _2int(data["head_y"]);
	int dot_x = _2int(data["dot_x"]);
	int dot_y = _2int(data["dot_y"]);

	if (data.has("char_code")) {
		if (data["char_code"]=="119") { // w
			if (not (head_x==0 and head_y==-1)) {
				head_x = 0;
				head_y = 1;
			}
		}
		else if (data["char_code"]=="115") { // s
			if (not (head_x==0 and head_y==1)) {
				head_x = 0;
				head_y = -1;
			}
		}
		else if (data["char_code"]=="97") { // a
			if (not (head_x==1 and head_y==0)) {
				head_x = -1;
				head_y = 0;
			}
		}
		else if (data["char_code"]=="100") { // d
			if (not (head_x==-1 and head_y==0)) {
				head_x = 1;
				head_y = 0;
			}
		}
		data["head_x"] = _2str(head_x);
		data["head_y"] = _2str(head_y);
	}

	bool game_over = false;
	int x = snake_data[0]+head_x;
	int y = snake_data[1]+head_y;
	if (x==dot_x and y==dot_y) {
		snake_data.push_back(0);
		snake_data.push_back(0);
		int n = snake_data.size();
		I(i,n-2) snake_data[n-1-i]=snake_data[n-1-i-2];
		snake_data[0] = x;
		snake_data[1] = y;
		rand_dot(snake_data, width, height);
	}
	else if (x<0 or y<0 or x>=width or y>=height or in_snake(snake_data, x, y)) {
		game_over = true;
	}
	else {
		int n = snake_data.size();
		I(i,n-2) snake_data[n-1-i]=snake_data[n-1-i-2];
		snake_data[0] = x;
		snake_data[1] = y;
	}
	data["snake"] = _vec2str(snake_data);

	rect bg;
	bg.x = _2str(0);
	bg.y = _2str(0);
	bg.width = _2str(width*line_width);
	bg.height = _2str(height*line_width);
	bg.fill = bg_color;

	rect dot;
	dot.x = _2str(dot_x*line_width);
	dot.y = _2str((height-1-dot_y)*line_width);
	dot.width = _2str(line_width);
	dot.height = _2str(line_width);
	dot.fill = dot_color;
	dot.stroke_width = _2str(0);

	SVG svg;
	svg += bg;
	svg += dot;

	I(i, snake_data.size()/2) {
		int x = snake_data[i*2];
		int y = snake_data[i*2+1];
		rect snake;
		snake.x = _2str(x*line_width);
		snake.y = _2str((height-1-y)*line_width);
		snake.width = _2str(line_width);
		snake.height = _2str(line_width);
		snake.fill = line_color;
		snake.stroke_width = _2str(0);
		svg += snake;
	}

	cout << svg;

	data["app_request"] = "500 example_9_game";
	data["key_request"] = "true";
	data.del("char_code");
	if (game_over) {
		data.del("app_request");
		data.del("key_request");
	}
}